/// A mediator for Photoshop plugins.
#include "photoshop.h"

HWND photoshopWindow = 0;
ATOM photoshopWindowClass = 0;
PrynState *photoshopState = 0;

BOOL WINAPI SetDllDirectoryA (LPCSTR lpPathName);
#define print(TEXT) prynPrintZ (photoshopState, TEXT)
#define printInteger(VALUE) prynPrintInteger (photoshopState, (int) (VALUE))

#define IS_INTRESOURCE(VALUE) ((uintptr_t) (VALUE) < 65536)
#define LONG_PTR uintptr_t

BOOL CALLBACK each (HMODULE hModule, LPCSTR lpszType, LPSTR lpszName, PhotoshopPlugin *plugin)
{
	print ("Resource: ");
	if (IS_INTRESOURCE (lpszType))
		prynPrintInteger (photoshopState, (int) lpszType);
	else
		print (lpszType);
	print (" ");
	if (IS_INTRESOURCE (lpszName))
		prynPrintInteger (photoshopState, (int) lpszName);
	else
		print (lpszName);
	print ("\n");
	return 1;
}

void listProperties (HANDLE library, char *type)
{
	int result = EnumResourceNamesA (library, type, (ENUMRESNAMEPROC) &each, 0);
	if (!result)
	{
		int error = GetLastError ();
		if (error != NO_ERROR && error != ERROR_RESOURCE_TYPE_NOT_FOUND)
			print ("Oh no something happened\n");
	}
}

static BOOL CALLBACK eachResourceType (HMODULE hModule, LPSTR lpszType, PhotoshopPlugin *plugin)
{
	if (!IS_INTRESOURCE (lpszType))
	{
		PrynString name = prynStringFromZ (lpszType);
		
		//prynPrintInteger (photoshopState, name.length);
		for (int i = 0; i < 4; i ++)
			prynPrintInteger (photoshopState, lpszType [i]), print (",");
		if (prynStringEqualLiteral (name, "AET"))
			print ("AET!");
	}
	
	print ("Type: ");
	if (IS_INTRESOURCE (lpszType))
		prynPrintInteger (photoshopState, (int) lpszType);
	else
	{
		print ("'");
		print (lpszType);
		print ("'");
	}
	print ("\n");
	listProperties (hModule, lpszType);
	return 1;
}


PrynResult load (PrynMediator *mediator, const char *filename)
{
	PrynState *state = prynMediatorState (mediator);
	HANDLE library = 0;
	PrynResult result = PrynResult_Success;
	PhotoshopPlugin plugin;
	void (*entryPoint) (short selector, void *pluginParameterBlock, long *pluginData, short *result) = 0;
	
	library = LoadLibraryA (filename);
	if (!library) return PrynResult_Failure;
	
	prynSetMemory (&plugin, 0, sizeof (PhotoshopPlugin));
	
	HRSRC resource = FindResource (library, MAKEINTRESOURCE (16000), "EXVW");
	prynAssert (resource, Failure);
	HGLOBAL resourceLoaded = LoadResource (library, resource);
	prynAssert (resourceLoaded, Failure);
	char *resourceData = (char *) LockResource (resourceLoaded);
	prynAssert (resourceData, Failure);
	DWORD resourceSize = SizeofResource (library, resource);
	prynAssert (resourceSize, Failure);
	
	print ("size: ");
	printInteger (resourceSize);
	print ("\n");
	char *resourceString = resourceData + 3;
	print (resourceString);
	print ("\n");
	
/*
dialog (
	placement: place_column,
	child_horizontal: align_center,
	name: '$$$/BMP/DialogName/AboutBMP=About Microsoft^R Windows^R Bitmap File Format',
	win_dialog_type: standard_plugin_about)
{
	user_item (placement: place_column, reverse: false, slot: 0, child_horizontal: align_center)
	{
		group (placement: place_row)
		{
			static_text (name: '$$$/BMP/AboutBoxName=Microsoft^R Windows^R Bitmap File Format');
			static_text (name: '$$$/AdobePlugin/VersionString/Version11=Version 11.0');
		}
		static_text (name: '$$$/BMP/Static/Line2=^C 1990-2008 Adobe Systems Incorporated. All rights reserved.');
		static_text (name: '$$$/BMP/Static/Line3=A plug-in image format module that reads and writes');
		static_text (name: '$$$/BMP/Static/Line4=Microsoft^R Windows^R and IBM^R OS/2^R BMP and RLE formats.');
	}
}
*/
	
	long pluginData = 0;
	short pluginResult = 0;
	PhotoshopAboutRecord about;
	PhotoshopPlatformDataWindows platform;
	
	platform.window = (intptr_t) photoshopWindow;
	about.platform = &platform;
	about.basic = 0;
	about.reference = 0;
	prynSetMemory (about.reserved, 0, sizeof (about.reserved));
	
	*(void **) &entryPoint = GetProcAddress (library, "ENTRYPOINT1");
	prynAssert (entryPoint, Failure);
	entryPoint (PhotoshopSelectorDisplayAboutBox, &about, &pluginData, &pluginResult);
	
	prynPrintLiteral (photoshopState, "Result: ");
	prynPrintInteger (photoshopState, pluginResult);
	prynPrintLiteral (photoshopState, "\n");
	
success:
	if (0)
	{
	failure:
		if (library)
			FreeLibrary (library);
	}
	
	return result;
}

static LRESULT CALLBACK windowProcedure (HWND window, UINT message, WPARAM a, LPARAM b)
{
	switch (message)
	{
		case 1: case 36: case 129: case 131: break;
		//default: prynPrintFormat (photoshopState, "Unknown Photoshop message: %d, %d, %d\n", message, a, b);
	}
	
	return DefWindowProcA (window, message, a, b);
}

PrynResult enable (PrynMediator *mediator)
{
	PrynState *state = prynMediatorState (mediator);
	HINSTANCE instance = GetModuleHandleA (0);
	
	SetErrorMode (0);
	SetDllDirectoryA ("Libraries\\Photoshop"); // FIXME - should use library path plus "\\Photoshop".
	photoshopState = state;
	
	WNDCLASS info;
	
	info.style = 0;
	info.lpfnWndProc = &windowProcedure;
	info.cbClsExtra = 0;
	info.cbWndExtra = 0;
	info.hInstance = instance;
	info.hIcon = 0;
	info.hCursor = 0;
	info.hbrBackground = 0;
	info.lpszMenuName = 0;
	info.lpszClassName = "Pryn Photoshop Mediator Class";

	photoshopWindowClass = RegisterClass (&info);
	if (!photoshopWindowClass) return PrynResult_Failure;
	
	photoshopWindow = CreateWindowA ((char *) photoshopWindowClass, "Pryn Photoshop Mediator Window", WS_OVERLAPPED, 0, 0, 100, 100, 0, 0, instance, 0);
	if (!photoshopWindow) return PrynResult_Failure;
	
	//return load (mediator, "C:\\Program Files\\Adobe\\Adobe Photoshop CS4\\Plug-ins\\File Formats\\BMP.8BI");
	return PrynResult_Success;
}

PrynLibraryEntryPoint (PrynLibrary *library)
{
	PrynResult result = 0;
	PrynMediator *mediator;
	
	prynSetLibraryNameLiteral (library, "Photoshop plugin mediator");
	prynSetLibraryDescriptionLiteral (library, "This allows access to Photoshop plugins.");
	
	result = prynCreateMediator (library, &mediator, prynStringLiteral ("Pryn.Photoshop"));
	if (result < 0) return result;
	
	prynSetMediatorNameLiteral (mediator, "Photoshop plugin");
	prynSetMediatorDescriptionLiteral (mediator, "This allows use of Adobe Photoshop plugins.");
	prynSetMediatorEnableFunction (mediator, &enable);
	
	return result;
}

